﻿using Newtonsoft.Json;
using RulesEngine;
using RulesEngine.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.Configuration;
using System.Text;
using System.Threading.Tasks;

namespace ZHello.RuleEngine
{
    /// <summary>
    /// 使用规则引擎
    /// https://www.cnblogs.com/whuanle/p/16830333.html
    /// 
    /// 规则验证系统，例如根据规则验证字段、执行函数验证当前流程、输出执行结果
    /// 动态代码引擎，能够将字符串转换为动态代码，利用表达式树完成工作
    /// 1. 安装nuget包 RulesEngine
    /// </summary>
    internal class UseRulesEngine
    {
        public class User
        {
            public int Age { get; set; }
            public bool IsOlder { get; set; } //Age >=65
        }
        public class Product
        {
            public float Price { get; set; }
            public bool Enable { get; set; } //Price >0
        }

        private const string RulesJson = @"
[
    {
        ""WorkflowName"":""Rule01"",
        ""Rules"":
        [
            {
                ""RuleName"":""UserAge"",
                ""Expression"":""Age >=65""
            }
        ]
    }
]";     
        public static async Task Run_ValidRule()
        {
            var usr0 = new User() { Age = 78, IsOlder = false };
            var usr1 = new User() { Age = 8, IsOlder = false };
            var workflow0 = JsonConvert.DeserializeObject<List<Workflow>>(RulesJson);

            var workflow1 = new List<Workflow>();
            workflow1.Add(new Workflow()
            {
                WorkflowName = "Rule01",
                Rules = new List<Rule>()
                {
                   new Rule()
                   {
                       RuleName ="UserAge",
                       Expression = "Age>=65"
                   },
                },
            });

            var engine0 = new RulesEngine.RulesEngine(workflow0.ToArray());
            var engine1 = new RulesEngine.RulesEngine(workflow0.ToArray());

            var t0 = engine0.ExecuteAllRulesAsync("Rule01", usr0);
            var t1 = engine0.ExecuteAllRulesAsync("Rule01", usr1);
            var t2 = engine1.ExecuteAllRulesAsync("Rule01", usr0);
            var t3 = engine1.ExecuteAllRulesAsync("Rule01", usr1);

            Task.WaitAll(
                t0.AsTask(), 
                t1.AsTask(), 
                t2.AsTask(), 
                t3.AsTask());

            var r0 = t0.Result;
            var r1 = t1.Result;
            var r2 = t2.Result;
            var r3 = t3.Result;

            var r00 = await engine0.ExecuteAllRulesAsync("Rule01", usr0);
            var r01 = await engine0.ExecuteAllRulesAsync("Rule01", usr1);
            var r02 = await engine1.ExecuteAllRulesAsync("Rule01", usr0);
            var r03 = await engine1.ExecuteAllRulesAsync("Rule01", usr1);

            Console.WriteLine(r0.TrueForAll(d => d.IsSuccess));
            Console.WriteLine(r1.TrueForAll(d => d.IsSuccess));
            Console.WriteLine(r2.TrueForAll(d => d.IsSuccess));
            Console.WriteLine(r3.TrueForAll(d => d.IsSuccess));
            Console.WriteLine(r00.TrueForAll(d => d.IsSuccess));
            Console.WriteLine(r01.TrueForAll(d => d.IsSuccess));
            Console.WriteLine(r02.TrueForAll(d => d.IsSuccess));
            Console.WriteLine(r03.TrueForAll(d => d.IsSuccess));
        }


    }
}
